package cn.ibizlab.util.adapter.config;

import com.alibaba.cloud.nacos.refresh.NacosContextRefresher;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.extern.slf4j.Slf4j;
import net.ibizsys.central.ISystemRuntimeSetting;
import net.ibizsys.central.cloud.core.spring.configuration.NacosServiceHubSetting;
import net.ibizsys.central.cloud.core.util.ConfigEntity;
import net.ibizsys.central.cloud.core.util.domain.DataSource;
import net.ibizsys.central.cloud.core.util.domain.DeploySystem;
import net.ibizsys.runtime.util.DataTypeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.*;

@Primary
@Slf4j
@Component
@ConditionalOnExpression(" '${ibiz.runtime.config.enableBootServiceHub:false}'.equals('true') ")
public class BootServiceHubSetting extends NacosServiceHubSetting {

    @JsonIgnore
    @JSONField(serialize = false)
    @Autowired
    BootServiceHub bootServiceHub;
    @Autowired
    NacosContextRefresher nacosContextRefresher;

    @PostConstruct
    public void postConstruct() {
        loadConfig();
    }

    /**
     * 加载本地配置
     * @throws Exception
     */
    @Override
    protected void onLoadConfig() throws Exception {

        //加载本地配置
        BootServiceHub.BootServiceHubSetting deployServiceHub = bootServiceHub.getServiceHub();
        if(deployServiceHub == null){
            throw new Exception("未定义配置");
        }

        onLoadConfig(JSON.parseObject(JSON.toJSONString(deployServiceHub), LinkedHashMap.class),true);
    }

    /**
     * 加载本地配置
     * @param config
     * @param bLocal
     * @throws Exception
     */
    @Override
    protected void onLoadConfig(Map config, boolean bLocal) throws Exception {

        Object value = config.get("enableappgateway");
        if (value != null) {
            this.setEnableAppGateway(value.toString().equalsIgnoreCase("true"));
        }

        if(!StringUtils.hasLength(this.getTempFolder())) {
            value = config.get("tempfolder");
            if (value != null) {
                this.setTempFolder(value.toString());
            }
        }

        if(!StringUtils.hasLength(this.getFileFolder())) {
            value = config.get("filefolder");
            if (value != null) {
                this.setFileFolder(value.toString());
            }
        }

        if(!StringUtils.hasLength(this.getFontFolder())) {
            value = config.get("fontfolder");
            if (value != null) {
                this.setFontFolder(value.toString());
            }
        }

        if(!StringUtils.hasLength(this.getReportFolder())) {
            value = config.get("reportfolder");
            if (value != null) {
                this.setReportFolder(value.toString());
            }
        }


        if(!StringUtils.hasLength(this.getTempFolder())) {
            this.setTempFolder(DEFAULT_TEMPFOLDER);
        }

        if(!StringUtils.hasLength(this.getFileFolder())) {
            this.setFileFolder(DEFAULT_FILEFOLDER);
        }

        if(!StringUtils.hasLength(this.getFontFolder())) {
            this.setFontFolder(DEFAULT_FONTFOLDER);
        }

        if(!StringUtils.hasLength(this.getReportFolder())) {
            this.setReportFolder(DEFAULT_REPORTFOLDER);
        }


        if(!StringUtils.hasLength(this.getCloudPluginServiceId())) {
            value = config.get("cloudpluginserviceid");
            if (value != null) {
                this.setCloudPluginServiceId(value.toString());
            }
        }


        value = config.get("enablereloadsystem");
        if (value != null) {
            this.setEnableReloadSystem(DataTypeUtils.getBooleanValue(value, this.isEnableReloadSystem()));
        }


        if(this.getNode() == null) {
            value = config.get("node");
            if (value != null) {
                this.setNode(Long.valueOf(value.toString()));
            }
        }


        Map<String, Object> systemSettings = null;
        if (config.get("systemsettings") instanceof Map) {
            systemSettings = (Map) config.get("systemsettings");
        }

        Object objDataSources = config.get("datasources");
        Map<String, DataSource> dataSourceMap = new HashMap<String, DataSource>();
        if (objDataSources instanceof Map) {
            List<DataSource> dataSourceList = new ArrayList<DataSource>();
            Map<String, Object> map = (Map<String, Object>) objDataSources;
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                DataSource dataSource = new DataSource();
                Object objDataSource = entry.getValue();
                if(objDataSource instanceof Map) {

                    Map<String, Object> source = (Map<String, Object>)objDataSource;
                    dataSource.putAll(source);
                    //进一步处理属性，这些属性将完全复制之数据源配置
                    for (Map.Entry<String, Object> item : source.entrySet()) {
                        String strKey = item.getKey().replace("-", "");
                        if(strKey.equals(item.getKey())) {
                            continue;
                        }
                        dataSource.set(strKey, item.getValue());
                    }

                    if (ObjectUtils.isEmpty(dataSource.getDriverClassName())) {
                        dataSource.setDriverClassName((String) dataSource.get("driver-class-name"));
                    }
                }
                else {
                    //加载本地配置
                    BootServiceHub.BootDatabaseInstance bootDatabaseInstance = bootServiceHub.getDatabaseInstance(objDataSource.toString());
                    if(bootDatabaseInstance == null) {
                        log.warn(String.format("未定义数据库实例[%1$s]配置，访问可能会出现问题", objDataSource.toString()));
                        continue;
                    }
                    ConfigEntity configEntity = new ConfigEntity(JSON.parseObject(JSON.toJSONString(bootDatabaseInstance), LinkedHashMap.class));
                    configEntity.copyTo(dataSource);
                }

                if (ObjectUtils.isEmpty(dataSource.getJdbcUrl())) {
                    dataSource.setJdbcUrl((String) dataSource.get("url"));
                }
                dataSource.setDataSourceId(entry.getKey());

                dataSourceList.add(dataSource);

                dataSourceMap.put(dataSource.getDataSourceId(), dataSource);
            }
            this.setDataSources(dataSourceList);
        }


        Object objDeploySystems = config.get("deploysystems");
        if (objDeploySystems instanceof List) {
            List<DeploySystem> deploySystemList = new ArrayList<DeploySystem>();
            List list = (List) objDeploySystems;
            for (Object item : list) {
                if (ObjectUtils.isEmpty(item)) {
                    continue;
                }

                //判断是否指定接口
                String strEnableAPIs = "";
                String strItem = item.toString();
                int nPos = strItem.indexOf(":");
                if(nPos != -1) {
                    item = strItem.substring(0, nPos);
                    strEnableAPIs = strItem.substring(nPos + 1);
                }

                //加载本地配置
                BootServiceHub.BootDeploySystem bootDeploySystem = bootServiceHub.getDeploySystem(item.toString());
                if (bootDeploySystem == null) {
                    throw new Exception(String.format("部署系统[%1$s]配置无效", item.toString()));
                }

                DeploySystem deploySystem = new DeploySystem();
                deploySystem.putAll(JSON.parseObject(JSON.toJSONString(bootDeploySystem), LinkedHashMap.class));
                deploySystem.setDeploySystemId(item.toString());

                if(this.getSystemRuntimeClass()!=null) {
                    String strSystemRuntimeClass = this.getSystemRuntimeClass().get(item);
                    if(StringUtils.hasLength(strSystemRuntimeClass)) {
                        deploySystem.setRuntimeClassName(strSystemRuntimeClass);
                    }
                }

                // 合并设置
                if (systemSettings != null) {
                    Map<String, Object> settings = new HashMap<String, Object>();
                    settings.putAll(systemSettings);
                    if (deploySystem.getSettings() != null) {
                        settings.putAll(deploySystem.getSettings());
                    }
                    deploySystem.setSettings(settings);
                }

                //放入启动接口
                if(StringUtils.hasLength(strEnableAPIs)) {
                    if(deploySystem.getSettings()==null) {
                        deploySystem.setSettings(new HashMap<String, Object>());
                    }
                    deploySystem.getSettings().put(ISystemRuntimeSetting.PARAM_ENABLEAPIS, strEnableAPIs);
                    //deploySystem.setAPIs(Arrays.asList(strInterfaces.split("[;]")));
                }

                //判断是否存在默认数据源
                String strDefaultDBInstTag = String.format("%1$s__default", deploySystem.getDeploySystemId());
                if(dataSourceMap.containsKey(strDefaultDBInstTag)) {
                    if(deploySystem.getSettings()==null) {
                        deploySystem.setSettings(new HashMap<String, Object>());
                    }
                    deploySystem.getSettings().put(ISystemRuntimeSetting.PARAM_DEFAULTDBINSTTAG, strDefaultDBInstTag);
                }



                deploySystemList.add(deploySystem);
            }
            this.setDeploySystems(deploySystemList);
        }

    }

    /**
     * 重新加载本地配置
     * @throws Exception
     */
    @Override
    protected void onReloadConfig() throws Exception {

        //加载本地配置
        BootServiceHub.BootServiceHubSetting deployServiceHub = bootServiceHub.getServiceHub();
        if(deployServiceHub == null){
            throw new Exception("未定义配置");
        }

        this.onReloadConfig(JSON.parseObject(JSON.toJSONString(deployServiceHub), LinkedHashMap.class));

    }

    /**
     * 重新加载本地配置
     * @param config
     * @throws Exception
     */
    protected void onReloadConfig(Map config) throws Exception {

        Map<String, Object> systemSettings = null;
        if (config.get("systemsettings") instanceof Map) {
            systemSettings = (Map) config.get("systemsettings");
        }

        Object objDataSources = config.get("datasources");
        Map<String, DataSource> dataSourceMap = new HashMap<String, DataSource>();
        if (objDataSources instanceof Map) {
            List<DataSource> dataSourceList = new ArrayList<DataSource>();
            Map<String, Object> map = (Map<String, Object>) objDataSources;
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                DataSource dataSource = new DataSource();
                Object objDataSource = entry.getValue();
                if(objDataSource instanceof Map) {

                    Map<String, Object> source = (Map<String, Object>)objDataSource;
                    dataSource.putAll(source);
                    //进一步处理属性，这些属性将完全复制之数据源配置
                    for (Map.Entry<String, Object> item : source.entrySet()) {
                        String strKey = item.getKey().replace("-", "");
                        if(strKey.equals(item.getKey())) {
                            continue;
                        }
                        dataSource.set(strKey, item.getValue());
                    }

                    if (ObjectUtils.isEmpty(dataSource.getDriverClassName())) {
                        dataSource.setDriverClassName((String) dataSource.get("driver-class-name"));
                    }
                }
                else {
                    //加载本地配置
                    BootServiceHub.BootDatabaseInstance bootDatabaseInstance = bootServiceHub.getDatabaseInstance(objDataSource.toString());
                    if(bootDatabaseInstance == null) {
                        log.warn(String.format("未定义数据库实例[%1$s]配置，访问可能会出现问题", objDataSource.toString()));
                        continue;
                    }
                    ConfigEntity configEntity = new ConfigEntity(JSON.parseObject(JSON.toJSONString(bootDatabaseInstance), LinkedHashMap.class));
                    configEntity.copyTo(dataSource);
                }

                if (ObjectUtils.isEmpty(dataSource.getJdbcUrl())) {
                    dataSource.setJdbcUrl((String) dataSource.get("url"));
                }
                dataSource.setDataSourceId(entry.getKey());

                dataSourceList.add(dataSource);

                dataSourceMap.put(dataSource.getDataSourceId(), dataSource);
            }
            this.setDataSources(dataSourceList);
        }
        else {
            this.setDataSources(new ArrayList<DataSource>());
        }


        Object objDeploySystems = config.get("deploysystems");
        if (objDeploySystems instanceof List) {
            List<DeploySystem> deploySystemList = new ArrayList<DeploySystem>();
            List list = (List) objDeploySystems;
            for (Object item : list) {
                if (ObjectUtils.isEmpty(item)) {
                    continue;
                }

                //判断是否指定接口
                String strEnableAPIs = "";
                String strItem = item.toString();
                int nPos = strItem.indexOf(":");
                if(nPos != -1) {
                    item = strItem.substring(0, nPos);
                    strEnableAPIs = strItem.substring(nPos + 1);
                }

                //加载本地配置
                Map deploySystemConfig = new LinkedHashMap();
                BootServiceHub.BootDeploySystem bootDeploySystem = bootServiceHub.getDeploySystem(item.toString());
                if (bootDeploySystem == null) {
                    throw new Exception(String.format("部署系统[%1$s]配置无效", item.toString()));
                }

                DeploySystem deploySystem = new DeploySystem();
                deploySystem.putAll(JSON.parseObject(JSON.toJSONString(bootDeploySystem), LinkedHashMap.class));
                deploySystem.setDeploySystemId(item.toString());

                // 合并设置
                if (systemSettings != null) {
                    Map<String, Object> settings = new HashMap<String, Object>();
                    settings.putAll(systemSettings);
                    if (deploySystem.getSettings() != null) {
                        settings.putAll(deploySystem.getSettings());
                    }
                    deploySystem.setSettings(settings);
                }

                //放入启动接口
                if(StringUtils.hasLength(strEnableAPIs)) {
                    if(deploySystem.getSettings()==null) {
                        deploySystem.setSettings(new HashMap<String, Object>());
                    }
                    deploySystem.getSettings().put(ISystemRuntimeSetting.PARAM_ENABLEAPIS, strEnableAPIs);
                    //deploySystem.setAPIs(Arrays.asList(strInterfaces.split("[;]")));
                }

                //判断是否存在默认数据源
                String strDefaultDBInstTag = String.format("%1$s__default", deploySystem.getDeploySystemId());
                if(dataSourceMap.containsKey(strDefaultDBInstTag)) {
                    if(deploySystem.getSettings()==null) {
                        deploySystem.setSettings(new HashMap<String, Object>());
                    }
                    deploySystem.getSettings().put(ISystemRuntimeSetting.PARAM_DEFAULTDBINSTTAG, strDefaultDBInstTag);
                }

                deploySystemList.add(deploySystem);
            }
            this.setDeploySystems(deploySystemList);
        }
        else {
            this.setDeploySystems(new ArrayList<DeploySystem>());
        }

    }

}
